package com.qqt.csr.archive.batch.task.etl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.qqt.csr.archive.batch.task.constants.ParamConstant;
import com.qqt.csr.archive.batch.task.context.ConversationArchiveTaskContext;
import com.qqt.csr.archive.batch.task.context.MessageArchiveTaskContext;
import com.qqt.csr.archive.enums.SourceType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.annotation.AfterStep;
import org.springframework.batch.core.annotation.BeforeStep;
import org.springframework.batch.item.ItemReader;

import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * @Author: yang hao
 * @Date: 2024/11/29 14:57
 * @Description: 归档读取器 基类
 **/
@Slf4j
public abstract class BaseArchiveReader<T> implements ItemReader<T> {

    /**
     * 会话归档任务上下文列表
     */
    protected ConcurrentLinkedQueue<ConversationArchiveTaskContext> conversationArchiveTaskContexts = new ConcurrentLinkedQueue<>();

    /**
     * 消息归档任务上下文列表
     */
    protected ConcurrentLinkedQueue<MessageArchiveTaskContext> messageArchiveTaskContexts = new ConcurrentLinkedQueue<>();

    /**
     * 步骤前置监听
     * @param execution {@link StepExecution} 步骤执行详情
     */
    @BeforeStep
    private void beforeStep(StepExecution execution) {
        log.info("归档任务开始执行, 步骤id:{}", execution.getStepName());
        // 获取任务参数
        JobParameters parameters = execution.getJobParameters();
        // 设置会话id列表
        String conversationIdsJson = parameters.getString(ParamConstant.CONVERSATION_IDS);
        if (StrUtil.isBlank(conversationIdsJson) || !JSONUtil.isTypeJSON(conversationIdsJson)) {
            throw new RuntimeException("归档任务任务参数会话id列表异常, conversationIdsJson:" + conversationIdsJson);
        }
        List<String> conversationIds = JSONUtil.toList(conversationIdsJson, String.class);
        // 设置渠道来源
        String sourceStr = parameters.getString(ParamConstant.SOURCE);
        if (StrUtil.isBlank(sourceStr)) {
            throw new RuntimeException("归档任务任务参数渠道来源异常, source:" + sourceStr);
        }
        SourceType source = SourceType.matchIgnoreCase(sourceStr);
        // 获取会话归档任务上下文
        this.conversationArchiveTaskContexts.addAll(conversationArchiveTaskContext(conversationIds, source));
        // 获取消息归档任务上下文
        this.messageArchiveTaskContexts.addAll(messageArchiveTaskContext(conversationIds, source));
        log.debug("会话归档任务上下文:{}", JSONUtil.toJsonStr(conversationArchiveTaskContexts));
        log.debug("消息归档任务上下文:{}", JSONUtil.toJsonStr(messageArchiveTaskContexts));
    }

    /**
     * 步骤后置监听
     * @param execution {@link StepExecution} 步骤执行详情
     * @return {@link ExitStatus} 步骤执行状态
     */
    @AfterStep
    private ExitStatus afterStep(StepExecution execution) {
        log.info("归档任务结束执行, 步骤详情:{}", execution);
        if (ExitStatus.UNKNOWN.equals(execution.getExitStatus())) {
            return ExitStatus.FAILED;
        }
        return execution.getExitStatus();
    }

    /**
     * 获取会话归档任务上下文
     * @param conversationIds {@link List<String>} 会话id列表
     * @param source {@link SourceType} 渠道来源
     * @return {@link List<ConversationArchiveTaskContext>} 会话归档任务上下文集
     */
    private List<ConversationArchiveTaskContext> conversationArchiveTaskContext(List<String> conversationIds, SourceType source) {
        if (conversationIds == null || conversationIds.isEmpty()) {
            return null;
        }
        return conversationIds.stream()
                .map(conversationId -> this.conversationArchiveTaskContext(conversationId, source))
                .toList();
    }

    /**
     * 获取会话归档任务上下文
     * @param conversationId {@link String} 会话id
     * @param source {@link SourceType} 渠道来源
     * @return {@link ConversationArchiveTaskContext} 会话归档任务上下文
     */
    private ConversationArchiveTaskContext conversationArchiveTaskContext(String conversationId, SourceType source) {
        return ConversationArchiveTaskContext.builder()
                .conversationId(conversationId)
                .source(source)
                .build();
    }

    /**
     * 获取消息归档任务上下文
     * @param conversationIds {@link List<String>} 会话id列表
     * @param source {@link SourceType} 渠道来源
     * @return {@link List<MessageArchiveTaskContext>} 消息归档任务上下文集
     */
    private List<MessageArchiveTaskContext> messageArchiveTaskContext(List<String> conversationIds, SourceType source) {
        if (conversationIds == null || conversationIds.isEmpty()) {
            return null;
        }
        return conversationIds.stream()
                .map(conversationId -> this.messageArchiveTaskContext(conversationId, source))
                .toList();
    }

    /**
     * 获取消息归档任务上下文
     * @param conversationId {@link String} 会话id
     * @param source {@link SourceType} 渠道来源
     * @return {@link MessageArchiveTaskContext} 消息归档任务上下文
     */
    private MessageArchiveTaskContext messageArchiveTaskContext(String conversationId, SourceType source) {
        return MessageArchiveTaskContext.builder()
                .conversationId(conversationId)
                .source(source)
                .build();
    }

}
